package com.flaremars.picker.utils;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;

import com.flaremars.picker.common.EdgeDetectorException;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;


/**
 * Created by FlareMars on 2016/3/3.
 */
public enum BitmapUtils {
    INSTANCE;

    /**
     * 质量压缩
     */
    private Bitmap compressImage(Bitmap image,int requestSize) {

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        image.compress(Bitmap.CompressFormat.JPEG, 100, baos);
        int options = 100;
        while ( baos.toByteArray().length / 1024 > requestSize) {
            baos.reset();
            image.compress(Bitmap.CompressFormat.JPEG, options, baos);
            options -= 10;
        }
        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
        return BitmapFactory.decodeStream(isBm, null, null);
    }

    /**
     * 等比例缩放
     */
    public Bitmap scaleImage(String srcPath,float requestHeight, float requestWidth,int requestSize) {
        if (requestSize == -1) {
            return BitmapFactory.decodeFile(srcPath);
        }

        BitmapFactory.Options newOpts = new BitmapFactory.Options();
        newOpts.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(srcPath,newOpts);

        newOpts.inJustDecodeBounds = false;
        int w = newOpts.outWidth;
        int h = newOpts.outHeight;
        int be = 1;
        if (w > h && w > requestWidth) {
            be = (int) (newOpts.outWidth / requestWidth);
        } else if (w < h && h > requestHeight) {
            be = (int) (newOpts.outHeight / requestHeight);
        }
        if (be <= 0)
            be = 1;
        newOpts.inSampleSize = be;
        return compressImage(BitmapFactory.decodeFile(srcPath, newOpts), requestSize);
    }

    /**
     * 图片旋转
     */
    public Bitmap adjustPhotoRotation(Bitmap bm, final int orientationDegree) {
        Matrix m = new Matrix();
        m.setRotate(orientationDegree, (float) bm.getWidth() / 2, (float) bm.getHeight() / 2);
        float targetX, targetY;
        if (orientationDegree == 90) {
            targetX = bm.getHeight();
            targetY = 0;
        } else {
            targetX = bm.getHeight();
            targetY = bm.getWidth();
        }

        final float[] values = new float[9];
        m.getValues(values);

        float x1 = values[Matrix.MTRANS_X];
        float y1 = values[Matrix.MTRANS_Y];

        m.postTranslate(targetX - x1, targetY - y1);

        Bitmap bm1 = Bitmap.createBitmap(bm.getHeight(), bm.getWidth(), Bitmap.Config.ARGB_8888);
        Paint paint = new Paint();
        Canvas canvas = new Canvas(bm1);
        canvas.drawBitmap(bm, m, paint);

        return bm1;
    }

    /**
     * 灰度处理
     */
    public Bitmap grayScaler(Bitmap src,ProgressListener listener) {
        Bitmap bitmapNew = src.copy(Bitmap.Config.ARGB_8888, true);
        for(int i = 0;i<bitmapNew.getWidth();i++) {
            for(int j =0;j<bitmapNew.getHeight();j++) {
                int col = bitmapNew.getPixel(i, j);
                int alpha = col&0xFF000000;
                int red = (col&0x00FF0000)>>16;
                int green = (col&0x0000FF00)>>8;
                int blue = (col&0x000000FF);
                int gray = (int)((float)red*0.3+(float)green*0.59+(float)blue*0.11);
                int newColor = alpha|(gray<<16)|(gray<<8)|gray;
                bitmapNew.setPixel(i, j, newColor);
            }
            listener.onProgress(bitmapNew);
        }
        return bitmapNew;
    }

    /**
     * 中值滤波处理
     */
    public Bitmap doMediaFilter(Bitmap src,ProgressListener listener) {
        Bitmap bitmapNew = src.copy(Bitmap.Config.ARGB_8888, true);
        int bitmapWidth = bitmapNew.getWidth();
        int bitmapHeight = bitmapNew.getHeight();

        int[] tpRed = new int[9];
        int[] tpGreen = new int[9];
        int[] tpBlue = new int[9];
        int mediaRed,mediaGreen,mediaBlue;

        for (int i = 1;i < bitmapWidth - 1;i++) {
            for (int j = 1;j < bitmapHeight - 1;j++) {
                int m = 0;
                for(int k=-1;k<2;k++){
                    for(int l=-1;l<2;l++){
                        int col = bitmapNew.getPixel(i, j);
                        tpRed[m] = (col&0x00FF0000)>>16;
                        tpGreen[m] = (col&0x0000FF00)>>8;
                        tpBlue[m] = (col&0x000000FF);
                        m++;
                    }
                }
                for(int rj=0; rj<8; rj++){
                    for(int ri=0; ri<8-rj; ri++){
                        if(tpRed[ri]>tpRed[ri+1]){
                            int Red_Temp = tpRed[ri];
                            tpRed[ri] = tpRed[ri+1];
                            tpRed[ri+1] = Red_Temp;
                        }
                    }
                }
                mediaRed = tpRed[4];
                for(int rj=0; rj<8; rj++){
                    for(int ri=0; ri<8-rj; ri++){
                        if(tpGreen[ri]>tpGreen[ri+1]){
                            int Green_Temp = tpGreen[ri];
                            tpGreen[ri] = tpGreen[ri+1];
                            tpGreen[ri+1] = Green_Temp;
                        }
                    }
                }
                mediaGreen= tpGreen[4];
                for(int rj=0; rj<8; rj++){
                    for(int ri=0; ri<8-rj; ri++){
                        if(tpBlue[ri]>tpBlue[ri+1]){
                            int Blue_Temp = tpBlue[ri];
                            tpBlue[ri] = tpBlue[ri+1];
                            tpBlue[ri+1] = Blue_Temp;
                        }
                    }
                }
                mediaBlue = tpBlue[4];
                bitmapNew.setPixel(i, j, 255<<24|mediaRed<<16|mediaGreen<<8|mediaBlue);
            }
            listener.onProgress(bitmapNew);
        }

        return bitmapNew;
    }

    /**
     * Canny算子提取边缘
     */
    public Bitmap cannyEdgeProcess(Bitmap src) {
        EdgeDetector edgeDetector=new EdgeDetector();
        edgeDetector.setSourceImage(src);
        edgeDetector.setThreshold(128);
        edgeDetector.setWidGaussianKernel(5);
        try {
            edgeDetector.process();
        }
        catch(EdgeDetectorException e) {
            System.out.println(e.getMessage());
        }
        return edgeDetector.getEdgeImage();
    }

    public interface ProgressListener {
        void onProgress(Bitmap bmp);
    }

    public void saveBitmapToFile(Bitmap bmp,String path,Bitmap.CompressFormat compressFormat) throws IOException {
        File file = new File(path);
        OutputStream out;
        out = new FileOutputStream(file);
        bmp.compress(compressFormat, 100, out);
        out.close();
    }
}
